package cn.itsource.ymjs.service.impl;

import cn.itsource.ymjs.config.HighlightResultMapper;
import cn.itsource.ymjs.doc.CourseDoc;
import cn.itsource.ymjs.query.CourseDocQuery;
import cn.itsource.ymjs.repository.CourseDocRepository;
import cn.itsource.ymjs.service.ICourseDocService;
import cn.itsource.ymjs.util.AjaxResult;
import cn.itsource.ymjs.util.PageList;
import cn.itsource.ymjs.vo.AggsVo;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.bucket.terms.StringTerms;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @program: ymjs
 * @author: Mr.Zhang
 * @create: 2022-02-08 18:33
 **/
@Service
public class CourseDocServiceImpl implements ICourseDocService {
    @Autowired
    private CourseDocRepository repository;

    @Autowired
    private HighlightResultMapper highlightResultMapper;

    @Autowired
    private ElasticsearchTemplate template;

    @Override
    public AjaxResult batchAdd(List<CourseDoc> docs) {
        repository.saveAll(docs);
        return AjaxResult.me();
    }

    @Override
    public AjaxResult batchDel(List<Long> ids) {
        Iterable<CourseDoc> docs = repository.findAllById(ids);
        repository.deleteAll(docs);
        return AjaxResult.me();
    }

    @Override
    public PageList<CourseDoc> queryPageData(CourseDocQuery query) {
        //1创建构建器
        NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();
        // 2.设置查询条件
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
        // 2.1关键字查询
        String keyword = query.getKeyword();
        if (!StringUtils.isEmpty(keyword)){
            boolQuery.must(QueryBuilders
                    .multiMatchQuery(keyword,"name","forUser","gradeName","tenantName","courseTypeName"));
            // .multiMatchQuery(keyword,"name","forUser","gradeName"));
        }
        // 2.2 dsl过滤  类型 机构 minprie maxprice
        // 按照类型过滤
        Long courseTypeId = query.getCourseTypeId();
        if (courseTypeId != null){
            boolQuery.filter(QueryBuilders.termQuery("courseTypeId",courseTypeId));
        }
        // 按照价格过滤
        Integer priceMin = query.getPriceMin();
        Integer priceMax = query.getPriceMax();
        if (priceMin != null && priceMax != null){
            boolQuery.filter(QueryBuilders.rangeQuery("price").gte(priceMin).lte(priceMax));
        } else if (priceMin != null && priceMax == null){
            boolQuery.filter(QueryBuilders.rangeQuery("price").gte(priceMin));
        } else if (priceMin == null && priceMax != null){
            boolQuery.filter(QueryBuilders.rangeQuery("price").lte(priceMax));
        }

        builder.withQuery(boolQuery);
        // 3.排序
        String sortField = query.getSortField();
        String sortFiledName = "onlineTime"; //默认按照最新
        switch (sortField.toLowerCase()){
//            case "xl": sortFiledName = "saleCount"; break; // 销量
            case "jg": sortFiledName = "price"; break; // 价格
//            case "pl": sortFiledName = "commentCount"; break; // 评论
//            case "rq": sortFiledName = "viewCount"; break; //
        }
        SortOrder defalutSortOrder = SortOrder.DESC; //默认是降序
        if (!query.getSortType().equals("desc")){
            defalutSortOrder = SortOrder.ASC;
        }
        builder.withSort(SortBuilders.fieldSort(sortFiledName).order(defalutSortOrder));
        // 4.分页
        builder.withPageable(PageRequest.of(query.getCurrentPage()-1,query.getPageSize()));
        /*Page<CourseDoc> page = repository.search(builder.build());
        if (page.getTotalElements() == 0){
            return new PageList<>();
        }*/
        // 5.高亮处理
        HighlightBuilder.Field field = new HighlightBuilder.Field("name").preTags("<font style='color:red'><b>").postTags("</b></font>");
        builder.withHighlightFields(field); // 名字高亮
        // 6.聚合,注意这里需要用keyword关键字
//        builder.addAggregation(AggregationBuilders.terms("tenantNameAggs").field("tenantName.keyword").size(20));
        builder.addAggregation(AggregationBuilders.terms("courseTypeNameAggs").field("courseTypeName.keyword").size(20));
        // 7.返回结构
        // 使用的时候不能用repository了
        AggregatedPage<CourseDoc> page = template.queryForPage(builder.build(),CourseDoc.class,highlightResultMapper);
        // 聚合 TODO
        // 声明一个map集合来装
//        HashMap<String, List<AggsVo>> aggs = new HashMap<>();
//        StringTerms tenantNameAggs = (StringTerms) page.getAggregation("tenantNameAggs");
//        List<AggsVo> tenantNameAggsVos  = getAggsVos(tenantNameAggs);
//        aggs.put("tenantNameAggs",tenantNameAggsVos);
//        StringTerms courseTypeNameAggs = (StringTerms) page.getAggregation("courseTypeNameAggs");
//        List<AggsVo> courseTypeNameAggsVos  = getAggsVos(courseTypeNameAggs);
//        aggs.put("courseTypeNameAggs",courseTypeNameAggsVos);
        if (page.getTotalElements() == 0){
            return new PageList<>();
        }
//        return new PageList<>(page.getTotalElements(),page.getContent(),aggs);
        return new PageList<>(page.getTotalElements(),page.getContent());
    }

//    private List<AggsVo> getAggsVos(StringTerms Terms) {
//        List<AggsVo> aggsVos = Terms.getBuckets().stream().map(bucket -> {
//            AggsVo aggsVo = new AggsVo();
//            String name = bucket.getKeyAsString();
//            long count = bucket.getDocCount();
//            aggsVo.setName(name);
//            aggsVo.setCount(count);
//            return aggsVo;
//        }).collect(Collectors.toList());
//        return aggsVos;
//    }

}
